﻿
using Quartz;
using Quartz.Impl;
using Quartz.Simpl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using System.Threading;
using System.Collections.Specialized;
using System.Drawing;
using Quartz.Xml.JobSchedulingData20;
using Quartz.Spi;
using iot.Models;
using CUGroup.IOT.Win.Winform.Jobs;


namespace CUGroup.IOT.Win.Winform
{
    /// <summary>
    /// 調度工廠
    /// </summary>
    public class QuartzManage
    {
        
        public static IScheduler scheduler;
        private static readonly object objlock = new object();

        static QuartzManage()
        {
            try
            {
                if (scheduler == null)
                {         
                    var props = new NameValueCollection {
                        {"quartz.scheduler.instanceName","myQquartz" },
                        { "quartz.threadPool.type", "Quartz.Simpl.DefaultThreadPool, Quartz" },
                        { "quartz.threadPool.threadCount", "60" }, 
                        { "quartz.threadPool.threadPriority", "Highest" },
                    };                   
                    var schedulerFactory = new StdSchedulerFactory(props);                    
                    scheduler = schedulerFactory.GetScheduler().Result;                 
                  
                    if (!scheduler.IsStarted)
                        scheduler.Start();     
                }
            }
            catch (Exception ex)
            {

            }

        }



        public async Task SchedulePlcDataCollectionJob(List<PlcInfo> cinfos)
        {
            JobDataMap dataMap = new JobDataMap
            {
                { "cinfos", cinfos },
            };
            TriggerKey triggerKey = new TriggerKey("collect_trigger");            
            JobKey jobKey = new JobKey("collect_jobkey");
            await scheduler.PauseTrigger(triggerKey);
            await scheduler.UnscheduleJob(triggerKey);
            await scheduler.DeleteJob(jobKey);

            IJobDetail job = JobBuilder.Create<PlcDataCollectionJob>()
                .WithIdentity("collect_group")
                .UsingJobData(dataMap)  
                .Build();            
            ITrigger trigger = TriggerBuilder.Create()
                .WithPriority(10)
                .WithIdentity("collect_trigger")
                .StartNow()
                .WithSimpleSchedule(x => x.WithInterval(TimeSpan.FromMilliseconds(5)).RepeatForever()).Build();
            
            await scheduler.ScheduleJob(job, trigger);
        }


        public async Task SchedulePutKafkaDataJob()
        {
            JobKey jobKey = new JobKey("PutKafkaDataJob_job");
            var jobs = await scheduler.GetCurrentlyExecutingJobs();


            bool isJobRunning = jobs.Any(j => j.JobDetail.Key == jobKey);

            if (scheduler.CheckExists(jobKey).Result)
            {
                if (isJobRunning)
                {
                    return;
                }
            }


            TriggerKey triggerKey = new TriggerKey("PutKafkaDataJob_trigger");


            await scheduler.PauseTrigger(triggerKey);
            await scheduler.UnscheduleJob(triggerKey);
            await scheduler.DeleteJob(jobKey);


            IJobDetail job = JobBuilder.Create<PutKafkaDataJob>()
                .WithIdentity("PutKafkaDataJob_job", "PutKafkaDataJob_job_group")
                .Build();

            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity(triggerKey)
                .WithSimpleSchedule(x => x.WithInterval(TimeSpan.FromSeconds(5)).RepeatForever())
                .StartNow().Build();
            await scheduler.ScheduleJob(job, trigger);
        }

        public async static void StartJobWithSimple<T>(string name, Action<SimpleScheduleBuilder> simpleInterval) where T : IJob
        {
            IJobDetail job = JobBuilder.Create<T>().WithIdentity(name + "_job", name + "_group").Build();
            ITrigger Simple = (ISimpleTrigger)TriggerBuilder.Create().StartNow()
                               .WithSimpleSchedule(simpleInterval)
                               .Build();

            await scheduler.ScheduleJob(job, Simple);
        }

     
        public async static void StartJobWithCron<T>(string name, string CronExpression, string groupName = "Defult_Job") where T : IJob
        {

            IJobDetail job = JobBuilder.Create<T>().WithIdentity(name + "_job", groupName + "_group").Build();

            ITrigger CronTrigger = (ICronTrigger)TriggerBuilder.Create().StartNow().WithIdentity(name + "_trigger", groupName + "_group")
                                    .WithCronSchedule(CronExpression, w => w.WithMisfireHandlingInstructionDoNothing())
                                    .Build();

            await scheduler.ScheduleJob(job, CronTrigger);
        }

     
        public async static void StartJobWithCron<T>(T tt, string name, int ms, string groupName = "Defult_Job") where T : IJob
        {

        }
  
        public static async void ModifyJob(string cronExpression, string name)
        {
           
            TriggerKey triggerKey = new TriggerKey(name + "_trigger", name + "_group");
            ITrigger trigger = await scheduler.GetTrigger(triggerKey);

            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.CronSchedule(cronExpression);
            trigger = trigger.GetTriggerBuilder().WithIdentity(triggerKey).WithSchedule(scheduleBuilder).Build();

            await scheduler.RescheduleJob(triggerKey, trigger);
        }

        public async static void DeleteJob(string name)
        {           
            TriggerKey triggerKey = new TriggerKey(name + "_trigger", name + "_group");
            
            JobKey jobKey = new JobKey(name + "_job", name + "_group");
            await scheduler.PauseTrigger(triggerKey);//暫停觸發器
            await scheduler.UnscheduleJob(triggerKey);//移除觸發器
            await scheduler.DeleteJob(jobKey);
        }

      
        public async static void DeleteJob(IJobDetail job, ITrigger trigger)
        {
            await scheduler.PauseTrigger(trigger.Key);
            await scheduler.UnscheduleJob(trigger.Key);
            await scheduler.DeleteJob(job.Key);
        }

      
        public async static void ShutDownJob()
        {
            if (scheduler != null && !scheduler.IsShutdown)
            {
                await scheduler.Shutdown(waitForJobsToComplete: true);
            }
        }


    }
}
